package com.jiufengxinxi.ts.device.callback;

import com.jiufengxinxi.ts.common.utils.FileUtil;
import com.jiufengxinxi.ts.device.interfaces.base.AlarmCallbackEnum;
import com.jiufengxinxi.ts.device.interfaces.base.AlarmCallbackVo;
import com.jiufengxinxi.ts.device.interfaces.base.HCNetSDK;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public abstract class IAlarmDeviceCallback implements HCNetSDK.FMSGCallBack {
    private static Logger logger= LoggerFactory.getLogger(IAlarmDeviceCallback.class);

    private String imgBasePath;

    private Map<String,String> fromMap = new HashMap<String,String>();

    private BlockingQueue<AlarmCallbackVo> VO_QUE = null;

    public IAlarmDeviceCallback(String imgBasePath,Map<String,String> fromMap){
        this.imgBasePath = imgBasePath;
        this.fromMap = fromMap;

        this.VO_QUE = new ArrayBlockingQueue<AlarmCallbackVo>(2000);

//        ExecutorServiceUtils.execute(new LoopThreadRunnable() {
//            @Override
//            public void loopElement() {
//                while(VO_QUE!=null&&VO_QUE.size()>0) {
//                    try {
//                        AlarmCallbackVo vo = VO_QUE.poll();
//                        callback(vo);
//                    }catch (Exception e){
//
//                    }
//                }
//            }
//
//            @Override
//            public int sleepTime() {
//                return 20;
//            }
//
//            @Override
//            public boolean endCondition() {
//                return true;
//            }
//
//            @Override
//            public boolean isUseLock() {
//                return false;
//            }
//
//            @Override
//            public String getName() {
//                return "check_VO_QUE";
//            }
//        });
    }

    public abstract void callback(AlarmCallbackVo vo);

    @Override
    public void invoke(NativeLong lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
        String sAlarmType = new String("lCommand=0x") +  Integer.toHexString(lCommand.intValue())+"   "
                +new String(pAlarmer.sDeviceIP+"   "+new String(pAlarmer.sDeviceName)
                +"   "+new String(pAlarmer.sSocketIP));
        Date now = new Date();
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");

        AlarmCallbackVo vo = new AlarmCallbackVo();

        vo.setFromIp(new String(pAlarmer.sDeviceIP).trim());
        vo.setFrom(fromMap.get(vo.getFromIp()));

        switch (lCommand.intValue()){
            case HCNetSDK.COMM_UPLOAD_PLATE_RESULT:{
                HCNetSDK.NET_DVR_PLATE_RESULT strPlateResult = new HCNetSDK.NET_DVR_PLATE_RESULT();
                strPlateResult.write();
                Pointer pPlateInfo = strPlateResult.getPointer();
                pPlateInfo.write(0, pAlarmInfo.getByteArray(0, strPlateResult.size()), 0, strPlateResult.size());
                strPlateResult.read();

                String plate = null;
                try {
                    plate=new String(strPlateResult.struPlateInfo.sLicense,"GBK");
                    plate = new String(getUTF8BytesFromGBKString(plate),"UTF-8");
                    sAlarmType = sAlarmType + "：交通抓拍上传，车牌："+ plate;
                    plate=plate.trim();
                    vo.setResult(plate);
                }catch (UnsupportedEncodingException e1) {
                    e1.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }



                vo.setAlarmCallbackEnum(AlarmCallbackEnum.PLATE_DETE);

                logger.info(String.format("时间：%s, 报警类型:%s, 报警设备IP地址:%s",dateFormat.format(now),sAlarmType,vo.getFromIp()));

                if(strPlateResult.dwPicLen>0){
                    //String[] imgPath = new String[strPlateResult.dwPicLen];

                    SimpleDateFormat sf = new SimpleDateFormat("HHmmssSSS");
                    String newName = plate+"_"+sf.format(new Date());
                    String path = String.format("%s/%s/%s",this.imgBasePath,vo.getFrom(),dateFormat.format(now));
                    FileUtil.createDir(path);
                    String file = String.format("%s/%s.jpg",path,newName);
                    FileOutputStream fout;
                    try {
                        logger.info("保存图片："+file);
                        //new File(file).createNewFile();
                        fout = new FileOutputStream(file);
                        //将字节写入文件
                        long offset = 0;
                        ByteBuffer buffers = strPlateResult.pBuffer1.getByteBuffer(offset, strPlateResult.dwPicLen);
                        byte [] bytes = new byte[strPlateResult.dwPicLen];
                        buffers.rewind();
                        buffers.get(bytes);
                        fout.write(bytes);
                        fout.close();
                        vo.setImagePaths(new String[]{file});
                    }catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }break;
            case HCNetSDK.COMM_ITS_PLATE_RESULT:{
                HCNetSDK.NET_ITS_PLATE_RESULT strItsPlateResult = new HCNetSDK.NET_ITS_PLATE_RESULT();
                strItsPlateResult.write();
                Pointer pItsPlateInfo = strItsPlateResult.getPointer();
                pItsPlateInfo.write(0, pAlarmInfo.getByteArray(0, strItsPlateResult.size()), 0, strItsPlateResult.size());
                strItsPlateResult.read();

                String plate = null;
                try {
                    plate=new String(strItsPlateResult.struPlateInfo.sLicense,"GBK");
                    plate = new String(getUTF8BytesFromGBKString(plate),"UTF-8");
                    sAlarmType = sAlarmType + ",车辆类型："+strItsPlateResult.byVehicleType + ",交通抓拍上传，车牌："+ plate;
                    plate=plate.trim();
                    vo.setResult(plate);
                }catch (UnsupportedEncodingException e1) {
                    e1.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                logger.info(String.format("时间：%s, 报警类型:%s, 报警设备IP地址:%s",dateFormat.format(now),sAlarmType,vo.getFromIp()));

                String[] imgpaths = new String[strItsPlateResult.dwPicNum];

                for(int i=0;i<strItsPlateResult.dwPicNum;i++){
                    if(strItsPlateResult.struPicInfo[i].dwDataLen>0)
                    {
                        SimpleDateFormat sf = new SimpleDateFormat("HHmmssSSS");
                        String newName = plate+"_"+sf.format(new Date());
                        String path = String.format("%s/%s/%s",this.imgBasePath,vo.getFrom(),dateFormat.format(now));
                        FileUtil.createDir(path);
                        String file = String.format("%s/%d_%s.jpg",path,i+1,newName);
                        logger.info("保存图片："+file);
                        FileOutputStream fout;
                        try {
                            //new File(file).createNewFile();
                            fout = new FileOutputStream(file);
                            //将字节写入文件
                            long offset = 0;
                            ByteBuffer buffers = strItsPlateResult.struPicInfo[i].pBuffer.getByteBuffer(offset, strItsPlateResult.struPicInfo[i].dwDataLen);
                            byte [] bytes = new byte[strItsPlateResult.struPicInfo[i].dwDataLen];
                            buffers.rewind();
                            buffers.get(bytes);
                            fout.write(bytes);
                            fout.close();
                            imgpaths[i] = file;
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
                vo.setImagePaths(imgpaths);

            }break;
        }

        vo.setResultTime(now);

        this.VO_QUE.offer(vo);
    }



    public static byte[] getUTF8BytesFromGBKString(String gbkStr) {
        int n = gbkStr.length();
        byte[] utfBytes = new byte[3 * n];
        int k = 0;
        for (int i = 0; i < n; i++) {
            int m = gbkStr.charAt(i);
            if (m < 128 && m >= 0) {
                utfBytes[k++] = (byte) m;
                continue;
            }
            utfBytes[k++] = (byte) (0xe0 | (m >> 12));
            utfBytes[k++] = (byte) (0x80 | ((m >> 6) & 0x3f));
            utfBytes[k++] = (byte) (0x80 | (m & 0x3f));
        }
        if (k < utfBytes.length) {
            byte[] tmp = new byte[k];
            System.arraycopy(utfBytes, 0, tmp, 0, k);
            return tmp;
        }
        return utfBytes;
    }
}
